package email

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"net/smtp"
	"strings"
	"sync"
	"time"
)

// EmailConfig 邮件服务器配置
type EmailConfig struct {
	SMTPServer string // SMTP服务器地址，如 "smtp.gmail.com:587"
	Username   string // 邮箱账号
	Password   string // 邮箱密码或授权码
	From       string // 发件人邮箱地址
}

// EmailMessageV2 邮件内容
type EmailMessageV2 struct {
	To          []string // 收件人列表
	CC          []string // 抄送列表
	BCC         []string // 密送列表
	Subject     string   // 邮件主题
	Body        string   // 邮件正文
	Attachments []string // 附件文件路径列表
}

// EmailSender 邮件发送器单例
type EmailSender struct {
	config EmailConfig
	mu     sync.RWMutex
}

var (
	instance        *EmailSender
	once            sync.Once
	emailDataChanV2 = make(chan *EmailMessageV2, 100000)
)

func InitV2(email EmailConfig) {
	// 获取邮件发送器单例实例
	sender := getEmailSender()
	// 配置邮件服务器
	sender.configure(email)

	go sendEmailV2()
}

func sendEmailV2() {
	for {
		select {
		case em := <-emailDataChanV2:
			err := getEmailSender().SendEmail(em)
			if err != nil {
				fmt.Println("邮件发送失败：", err)
			}
		default:
			time.Sleep(time.Second)
		}
	}
}

// GetEmailSender 获取邮件发送器实例（单例模式）
func getEmailSender() *EmailSender {
	once.Do(func() {
		instance = &EmailSender{}
	})
	return instance
}

// Configure 配置邮件服务器
func (es *EmailSender) configure(config EmailConfig) {
	es.mu.Lock()
	defer es.mu.Unlock()
	es.config = config
}

// GetConfig 获取当前配置
func (es *EmailSender) GetConfig() EmailConfig {
	es.mu.RLock()
	defer es.mu.RUnlock()
	return es.config
}

// SendEmail 发送邮件
func (es *EmailSender) SendEmail(message *EmailMessageV2) error {
	es.mu.RLock()
	config := es.config
	es.mu.RUnlock()

	// 验证必要参数
	if len(message.To) == 0 {
		return fmt.Errorf("收件人不能为空")
	}
	if config.SMTPServer == "" || config.Username == "" || config.Password == "" {
		return fmt.Errorf("邮件服务器配置不完整，请先调用Configure()方法")
	}

	// 构建收件人列表（包括To, CC, BCC）
	recipients := append(append(message.To, message.CC...), message.BCC...)

	// 创建认证
	auth := smtp.PlainAuth("", config.Username, config.Password, strings.Split(config.SMTPServer, ":")[0])

	// 构建邮件内容
	emailContent, err := es.buildEmailContent(config.From, message)
	if err != nil {
		return fmt.Errorf("构建邮件内容失败: %v", err)
	}
	// 发送邮件
	err = smtp.SendMail(config.SMTPServer, auth, config.From, recipients, []byte(emailContent))
	if err != nil {
		return fmt.Errorf("发送邮件失败: %v", err)
	}

	return nil
}

// buildEmailContent 构建邮件内容（包括 headers 和 body）
func (es *EmailSender) buildEmailContent(from string, message *EmailMessageV2) (string, error) {
	var headers []string

	// 添加邮件头
	headers = append(headers, fmt.Sprintf("From: %s", from))
	headers = append(headers, fmt.Sprintf("To: %s", strings.Join(message.To, ",")))
	if len(message.CC) > 0 {
		headers = append(headers, fmt.Sprintf("Cc: %s", strings.Join(message.CC, ",")))
	}
	headers = append(headers, fmt.Sprintf("Subject: =?UTF-8?B?%s?=", base64.StdEncoding.EncodeToString([]byte(message.Subject))))
	headers = append(headers, "MIME-Version: 1.0")

	// 构建邮件体
	var bodyParts []string
	bodyParts = append(bodyParts, message.Body)

	// 处理附件
	boundary := "Boundary_" + randomString(16)
	if len(message.Attachments) > 0 {
		headers = append(headers, fmt.Sprintf("Content-Type: multipart/mixed; boundary=%s", boundary))

		// 添加正文部分
		bodyParts = []string{
			fmt.Sprintf("--%s", boundary),
			"Content-Type: text/plain; charset=UTF-8",
			"",
			message.Body,
		}

		// 添加附件
		for _, file := range message.Attachments {
			part, err := createAttachmentPart(boundary, file)
			if err != nil {
				return "", err
			}
			bodyParts = append(bodyParts, part)
		}

		// 添加结束边界
		bodyParts = append(bodyParts, fmt.Sprintf("--%s--", boundary))
	} else {
		// 没有附件时使用简单格式
		headers = append(headers, "Content-Type: text/plain; charset=UTF-8")
	}

	// 组合所有部分
	headersStr := strings.Join(headers, "\r\n")
	bodyStr := strings.Join(bodyParts, "\r\n")

	return fmt.Sprintf("%s\r\n\r\n%s", headersStr, bodyStr), nil
}

// createAttachmentPart 创建附件部分
func createAttachmentPart(boundary, filePath string) (string, error) {
	// 读取文件内容
	fileContent, err := ioutil.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("读取附件文件失败: %v", err)
	}

	// 获取文件名
	parts := strings.Split(filePath, "/")
	filename := parts[len(parts)-1]

	// 构建附件部分
	var attachmentParts []string
	attachmentParts = append(attachmentParts, fmt.Sprintf("--%s", boundary))
	attachmentParts = append(attachmentParts, fmt.Sprintf("Content-Type: application/octet-stream; name=\"%s\"", filename))
	attachmentParts = append(attachmentParts, fmt.Sprintf("Content-Disposition: attachment; filename=\"%s\"", filename))
	attachmentParts = append(attachmentParts, "Content-Transfer-Encoding: base64")
	attachmentParts = append(attachmentParts, "")
	attachmentParts = append(attachmentParts, base64.StdEncoding.EncodeToString(fileContent))

	return strings.Join(attachmentParts, "\r\n"), nil
}

// randomString 生成随机字符串用于boundary
func randomString(n int) string {
	const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, n)
	for i := range b {
		b[i] = letters[byte(i)%byte(len(letters))]
	}
	return string(b)
}

func SendToChanV2(em *EmailMessageV2) {
	emailDataChanV2 <- em
}
